class Actor
  attr_accessor :pos, :vel, :speed, :max_speed, :drag, :gravity
  
  class << self
    attr_reader :actors
    
    def <<(actor)
      @actors ||= []
      @actors << actor unless @actors.include? actor
    end
    
    def include?(actor)
      @actors and @actors.include? actor
    end
    
    def clear
      @actors = []
    end
    
    def delete(actor)
      @actors.delete actor if @actors
    end
    
    def draw_all
      @actors.each { |actor| actor.draw } if @actors
    end
    
    def each
      @actors.each { |actor| yield actor }
    end
    
    def update_all
      @actors.each { |actor| actor.update } if @actors
    end
  end
  
  def initialize
    @created_at = now
    @width ||= 1
    @height ||= 1
    @pos ||= Point.new
    @vel ||= Point.new
    @drag ||= 0.9
    @gravity ||= 0.2
  end

  def add_to_world
    Actor << self
  end
  
  def bottom
    @pos.y - @pos.z
  end
  
  def draw
  end
  
  def in_world?
    Actor.include? self
  end

  def left
    @pos.x - @width / 2
  end
  
  def move(x, y=0, z=0)
    return @pos += x if x.is_a? Point
    @pos.x += x
    @pos.y += y
    @pos.z += z
    @pos
  end
  
  def on_ground?
    @pos.z <= 0
  end
  
  def push(x, y=0, z=0)
    return @vel += x if x.is_a? Point
    @vel.x += x
    @vel.y += y
    @vel.z += z
    vel
  end
  
  def remove_from_world
    Actor.delete self
  end

  def right
    left + @width
  end
  
  def top
    bottom - @height
  end
  
  def touched(actor)
  end
  
  def update
    @speed = @vel.length
    @vel = @vel / @speed * @max_speed if @max_speed and @speed > @max_speed
    @pos = @pos + @vel
    @pos.z -= @gravity unless on_ground?
    @pos.z = 0 if @pos.z < 0
    @vel *= @drag
  end

  def warp(x, y=0, z=0)
    return @pos = x if x.is_a? Point
    @pos.x = x
    @pos.y = y
    @pos.z = z
    pos
  end
  
  def z_order
    (@pos.y - @pos.z) * $window.width - @pos.x # top-to-bottom, left-to-right
  end
end
